home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / rexx / soundex.rexx < prev    next >
OS/2 REXX Batch file  |  1995-09-21  |  11KB  |  333 lines

  1. /****************************************************************************
  2.  *                                                                          *
  3.  * $VER: Soundex 1.02 (24 Aug 1995)
  4.  *                                                                          *
  5.  *                      Written by Freddy Ariës                             *
  6.  *                                                                          *
  7.  * Program for Scion Genealogist 4.0 and above (no guarantees are given     *
  8.  * for lower versions). This program should ask the user for a (last)name,  *
  9.  * and output the list of names in the current Scion database that match    *
  10.  * the entered name, using the SOUNDEX method of name comparison.           *
  11.  * Scion Genealogist must be running for this script to work.               *
  12.  *                                                                          *
  13.  * For those who don't know what SOUNDEX is, here is a short intro:         *
  14.  *                                                                          *
  15.  * The Soundex system is the means established by the National Archives     *
  16.  * to index the U.S. censuses (beginning with 1880). It codes together      *
  17.  * surnames of the same and similar sounds but of variant spellings.        *
  18.  * Soundexes are arranged by state, Soundex code of the surname, and        *
  19.  * given name.                                                              *
  20.  *                                                                          *
  21.  * Soundex codes begin with the first letter of the surname followed by a   *
  22.  * three-digit code that represents the (first three) remaining consonants. *
  23.  * This Soundex converter will do the tricky work for you and capture the   *
  24.  * nuances of the coding scheme (such as coding adjacent like letters as    *
  25.  * one). Just enter the surname that you want coded.                        *
  26.  *                                                                          *
  27.  * Soundex Coding Guide                                                     *
  28.  *  1 = B,P,F,V                                                             *
  29.  *  2 = C,S,G,J,K,Q,X,Z                                                     *
  30.  *  3 = D,T                                                                 *
  31.  *  4 = L                                                                   *
  32.  *  5 = M,N                                                                 *
  33.  *  6 = R                                                                   *
  34.  *                                                                          *
  35.  * The letters A,E,I,O,U,Y,H and W are not coded.                           *
  36.  *                                                                          *
  37.  * Note that surname prefixes such as Van, Von, Di, De, Le, D', dela, or    *
  38.  * du are sometimes disregarded in alphabetizing and in coding.             *
  39.  * Therefor it is wise to code it with and without the prefix because it    *
  40.  * may be listed under either code. Eg. Van Hoesen could be coded as        *
  41.  * VanHoesen or as Hoesen.                                                  *
  42.  *                                                                          *
  43.  * TO DO:                                                                   *
  44.  *  - Automatically do the above coding (2 alternatives) for prefixes.      *
  45.  *  - Suggestions, comments, bugreports, donations, etc. are appreciated.   *
  46.  *                                                                          *
  47.  * FIXED (v1.02):                                                           *
  48.  * - 2 consecutive letters with the same code are now treated as one        *
  49.  *   eg. LLOYD=LOYD -> [LD=L300], and JACKSON (CKS are all 2) -> [JCN=J250] *
  50.  *                                                                          *
  51.  ****************************************************************************/
  52.  
  53. options failat 20; options results
  54. arg srchstr outname outval
  55.  
  56. versionstr = "1.02"
  57. usereq = 1; /* change this to 0 if you don't want to use reqtools */
  58. outp = 1; output = stdout
  59. NL = '0A'x
  60. plwidth = 78;  /* linewidth of the printer */
  61. sxlen = 3;  /* the length of the soundex-code is usually 3,
  62.          * but if you insist, you can use a longer code
  63.          */    
  64.  
  65. signal on IOERR
  66.  
  67. /* parse command line options, to enable calling the script automatically,
  68.  * eg. from a function key
  69.  */
  70.  
  71. do while srchstr = '?'
  72.   writeln(stdout, "SEARCHNAME/A,OUTFILE/A,QUIET/S,NOREQ/S ")
  73.   pull srchstr outname outval
  74. end
  75.  
  76. if srchstr ~= "" then do
  77.   if srchstr = "QUIET" | srchstr = "NOREQ" then do
  78.     outval = srchstr; srchstr = ""
  79.   end
  80. end
  81.  
  82. if outval = "QUIET" then do
  83.   outp = 0; usereq = 0
  84. end
  85. else if outval = "NOREQ" then usereq = 0
  86.  
  87. if usereq & ~show('l','rexxreqtools.library') then do
  88.   if exists('libs:rexxreqtools.library') then
  89.     call addlib('rexxreqtools.library',0,-30,0)
  90.   else do
  91.     usereq = 0; outp = 1
  92.     Tell("Unable to open rexxreqtools.library - using text output")
  93.   end
  94. end
  95.  
  96. /* These first few lines are stolen from Peter Billings - thanks Peter ;-) */
  97. if ~show('P','SCIONGEN') then do
  98.   TermError('I am sorry to say that the SCION Genealogist' || NL ||,
  99.     'database is not available. Please start the' || NL ||,
  100.     'SCION program BEFORE using this script!')
  101. end
  102.  
  103. /* Printer Codes (some of which are currently unused): */
  104. ESC = '1B'x
  105. prtinit = ESC||"#1";     /* ESC#1 initialize      */
  106. prtundon = ESC||"[4m";   /* ESC[4m underline on   */
  107. prtundoff = ESC||"[24m"; /* ESC[24m underline off */
  108. prtdson = ESC||"[1m";    /* ESC[1m boldface on    */
  109. prtdsoff = ESC||"[22m";  /* ESC[22m boldface off  */
  110. prtnlqon = ESC||"[2"||'22'x||"z";  /* ESC[2"z NLQ on  */
  111. prtnlqoff = ESC||"[1"||'22'x||"z"; /* ESC[1"z NLQ off */
  112.  
  113. MyPort = "SCIONGEN"
  114. Address value MyPort
  115. GETDBNAME
  116. dbname = upper(RESULT)
  117.  
  118. if outp & ~usereq then do
  119.   Tell("Scion SOUNDEX script v"||versionstr||" by Freddy Ariës")
  120.   Tell("Database: "||dbname|| NL)
  121. end
  122.  
  123. if srchstr = '' then do
  124.   if usereq then do
  125.     srchname = rtgetstring(,'Enter the surname to search for: '||,
  126.             NL,'Input Request:','_Continue','rt_pubscrname = '||PSCR)
  127.     if srchname = '' then
  128.       EXIT
  129.     srchname = upper(srchname)
  130.   end
  131.   else do
  132.     TellNN("Enter the surname to search for: ")
  133.     pull srchname
  134.   end
  135. end
  136. else do
  137.   srchname = upper(srchstr)
  138. end
  139.  
  140. if usereq then do
  141.   if outname = "" then do
  142.     odev = rtezrequest('Current Scion database: '||dbname||,
  143.       NL||'Where should the output be sent to?'||,
  144.       NL,' _File |_Printer|_Screen|_Nowhere','Scion SOUNDEX script v'||versionstr||' by Freddy Ariës','rt_pubscrname = '||PSCR)
  145.     select
  146.       when odev = 1 then do
  147.         /* We need a file requester for further data */
  148.         dblen = length(dbname)
  149.         if dblen>6 & right(dbname, 6)=".SCION" then
  150.           dbname=left(dbname, dblen - 6)
  151.         outname = rtfilerequest(,dbname||'.SDX','Output filename',,'rtfi_buffer = true   rt_pubscrname = '||PSCR||'   rtfi_initialpath = RAM:',)
  152.         if outname = '' then
  153.           outname = dbname||'.SDX'
  154.       end
  155.       when odev = 2 then
  156.         outname = 'PRT:'
  157.       when odev = 3 then
  158.         outname = 'STDOUT'
  159.       otherwise
  160.         EXIT
  161.         /* You selected 'Nowhere' */
  162.     end
  163.   end
  164.  
  165.   useirn = rtezrequest('Do you want to output the IRNs'||,
  166.             NL||'(the record numbers) as well?'||,
  167.             '',' _Yes| _No ','Input Request:','rt_pubscrname = '||PSCR)
  168. end
  169. else do
  170.   if outname = "" then do
  171.     Tell("Enter output file (filename with complete path, or PRT: for printer,")
  172.     TellNN("or STDOUT for screen): ")
  173.     pull outname
  174.     if outname = "" then
  175.       outname = "STDOUT"
  176.   end
  177.  
  178.   TellNN("Do you want to output the IRNs (numbers) as well (y/n)? ")
  179.   pull instr
  180.   Tell("")
  181.   if left(instr, 1) = "Y" then useirn = 1
  182.   else useirn = 0
  183. end
  184.  
  185. /* convert the entered string to a SOUNDEX search pattern */
  186. spat = GetSoundex(srchname)
  187. if spat = 'A' then do
  188.   TermError("Unable to create soundex code for name string!")
  189. end
  190.  
  191. /* Make a list of all the people in the database whose surname matches
  192.  * the given lastname (ie. matching soundex codes)
  193.  */
  194.  
  195. OpenPrinter()
  196.  
  197. GETTOTALIRN
  198. TotalIRN = RESULT
  199. do i = 1 to TotalIRN
  200.   EXISTPERSON i
  201.   if RESULT = 'YES' then
  202.   do
  203.     GETLASTNAME i
  204.     lname = upper(RESULT)
  205.     ccode = GetSoundex(lname)
  206.     if ccode = spat then do
  207.       /* Found a match - output the name */
  208.       GETFIRSTNAME i
  209.       fnames = RESULT
  210.       if useirn then
  211.     oline = left(i||".     ",6)
  212.       else
  213.         oline = ""
  214.       oline = oline||lname||", "||fnames
  215.       writeln(prtdev, oline)
  216.     end
  217.   end
  218. end
  219.  
  220. writeln(prtdev, prtnlqoff); /* ESC[1"z NLQ off */
  221. close(prtdev)
  222. EXIT
  223.  
  224. /* Some special purpose routines for Soundex */
  225.  
  226. GetSoundex: PROCEDURE EXPOSE sxlen
  227. parse arg nstr
  228.   found = 0
  229.   wstr = upper(nstr)
  230.  
  231.   ix = 1; wix = 0; wval = 0
  232.   wlen = length(wstr)
  233.   code = 'A';
  234.  
  235.   /* Find first letter from the string */
  236.   do while ~found & (wix < wlen)
  237.     wix = wix + 1
  238.     c = substr(wstr,wix,1)
  239.     if c >= 'A' & c <= 'Z' then do
  240.       found = 1
  241.       code = c
  242.     end
  243.     else if c = ',' then wix = wlen
  244.     /* Everything after a comma is skipped - for now.
  245.      * The assumption is made that everything after a comma is prefixes.
  246.      * eg. Von Hoesen can be stored as "Von Hoesen", or as "Hoesen, Von"
  247.      * In the first case, it will become "V525", in the 2nd "H250"
  248.      */
  249.   end
  250.   if ~found then return code
  251.   pv = GetValue(code)
  252.  
  253.   /* Append a 3-digit (sxlen-size) code to the letter */
  254.   do while ix <= sxlen & wix < wlen
  255.     wix = wix + 1
  256.     wval = GetValue(substr(wstr,wix,1))
  257.     if wval > 0 & wval ~= pv then do
  258.       code = code||wval
  259.       say "adding "substr(wstr,wix,1)
  260.       pv = wval
  261.       ix = ix + 1
  262.     end
  263.     else if wval ~= pv then pv = ''
  264.   end
  265.  
  266.   do while ix <= sxlen
  267.     code = code||"0"
  268.     ix = ix + 1
  269.   end
  270. return code
  271.  
  272. GetValue: PROCEDURE
  273. parse arg c
  274.   if c = 'B' | c = 'F' | c = 'P' | c = 'V' then return 1
  275.   if c = 'C' | c = 'G' | c = 'J' | c = 'K' | c = 'Q' | c = 'S' | c = 'X' | c = 'Z' then return 2
  276.   if c = 'D' | c = 'T' then return 3
  277.   if c = 'L' then return 4
  278.   if c = 'M' | c = 'N' then return 5
  279.   if c = 'R' then return 6
  280.  
  281. return 0
  282.  
  283. /* General purpose requesters */
  284.  
  285. OpenPrinter:
  286. /* Open the printer device and print out a nice header */
  287. if outname = "STDOUT" then
  288.   prtdev = stdout
  289. else do
  290.   prtdev = 'PRINTER'
  291.   if ~open(prtdev, outname, 'w') then
  292.     TermError("ERROR: Failed to open output file!")
  293. end
  294. writeln(prtdev, prtinit||prtnlqon)
  295. prtstr = prtundon||prtdson||"SOUNDEX listing for "||srchname||" (Soundex code: "||spat||")"||prtdsoff||prtundoff
  296. writeln(prtdev, prtstr)
  297. prtstr = prtdson||"Report printed on: "||date()||"        "||"database: "||dbname||prtdsoff
  298. writeln(prtdev, prtstr)
  299. prtstr = copies('=', plwidth)
  300. writeln(prtdev, prtstr)
  301. return 0
  302.  
  303. Tell: PROCEDURE EXPOSE outp
  304. parse arg str
  305. if outp then
  306.   writeln(stdout, str)
  307. return 0
  308.  
  309. TellNN: PROCEDURE EXPOSE outp
  310. parse arg str
  311. if outp then
  312.   writech(stdout, str)
  313. return 0
  314.  
  315. TermError: PROCEDURE EXPOSE outp prtdev usereq PSCR
  316. parse arg str
  317. /* If you turned off stdout, no error messages will be shown! */
  318. if usereq then
  319.   rtezrequest(str,'E_xit','Soundex Message:','rt_pubscrname = '||PSCR)
  320. else do
  321.   Tell(str || '0A'x)
  322. end
  323. close(prtdev)
  324. EXIT
  325.  
  326. /* Let's make sure you get a nice message when you turn off the printer :-) */
  327.  
  328. IOERR:
  329. bline = SIGL
  330. say "I/O error #"||RC||" detected in line "||bline||":"
  331. say sourceline(bline)
  332. EXIT
  333.